﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using InterpriseSuiteEcommerceCommon.DTO;
using InterpriseSuiteEcommerceCommon.Extensions;
using InterpriseSuiteEcommerceCommon.Tool;

namespace InterpriseSuiteEcommerceCommon.InterpriseIntegration
{
    public class MobileShoppingCartPageLiteralRenderer : IShoppingCartHTMLLiteralRenderer
    {
        #region IShoppingCartHTMLLiteralRenderer Members

        public void Render(InterpriseShoppingCart cart, ref StringBuilder output)
        {
            bool vatenabled = AppLogic.AppConfigBool("VAT.Enabled");
            var root = new XElement(DomainConstants.XML_ROOT_NAME);
            if (cart.IsEmpty())
            {
                string cartEmptyText = string.Empty;
                if (cart.CartType == CartTypeEnum.ShoppingCart)
                {
                    var t1 = new Topic("MobileEmptyCartText", cart.ThisCustomer.LocaleSetting, cart.SkinID, null);
                    cartEmptyText = t1.Contents;
                }

                if (cart.CartType == CartTypeEnum.WishCart)
                {
                    var t1 = new Topic("MobileEmptyWishListText", cart.ThisCustomer.LocaleSetting, cart.SkinID, null);
                    cartEmptyText = t1.Contents;
                }

                if (cart.CartType == CartTypeEnum.GiftRegistryCart)
                {
                    var t1 = new Topic("MobileEmptyGiftRegistryText", cart.ThisCustomer.LocaleSetting, cart.SkinID, null);
                    cartEmptyText = t1.Contents;
                }

                root.Add(new XElement("EMPTY_CART_TEXT", cartEmptyText));
            }
            else
            {
                bool showPicsInCart = AppLogic.AppConfigBool("ShowPicsInCart");
                bool showLinkBack = AppLogic.AppConfigBool("LinkToProductPageInCart");
                bool hideUnitMeasure = AppLogic.AppConfigBool("HideUnitMeasure");
                bool showShipDateInCart = AppLogic.AppConfigBool("ShowShipDateInCart");
                bool showStockHints = AppLogic.AppConfigBool("ShowStockHints");
                
                root.Add(new XElement("SKINID", cart.SkinID));

                foreach (CartItem cartItem in cart.CartItems)
                {
                    var xmlcartItem = new XElement("CART_ITEMS");
                    xmlcartItem.Add(new XElement("CART_ITEM_ID", cartItem.m_ShoppingCartRecordID));
                    root.Add(xmlcartItem);

                    string productLinkHref = InterpriseHelper.MakeItemLink(cartItem.ItemCode);
                    string displayName = cartItem.DisplayName.ToHtmlEncode();
                    xmlcartItem.Add(new XElement("PRODUCTLINKNAME", displayName));
                    xmlcartItem.Add(new XElement("LINKBACK", showLinkBack.ToStringLower()));

                    switch (cartItem.ItemType)
                    {
                        case Interprise.Framework.Base.Shared.Const.ITEM_TYPE_MATRIX_GROUP:

                        #region "ITEM_TYPE_MATRIX_ITEM"
                        case Interprise.Framework.Base.Shared.Const.ITEM_TYPE_MATRIX_ITEM:

                            using (var con = DB.NewSqlConnection())
                            {
                                con.Open();
                                using (var reader = DB.GetRSFormat(con, String.Format("SELECT ItemCode FROM InventoryMatrixItem with (NOLOCK) WHERE MatrixItemCode = {0}", DB.SQuote(cartItem.ItemCode))))
                                {
                                    if (reader.Read())
                                    {
                                        productLinkHref = InterpriseSuiteEcommerceCommon.InterpriseHelper.MakeItemLink(DB.RSField(reader, "ItemCode"));
                                    }
                                }
                            }

                            if (showLinkBack && !cartItem.IsCheckoutOption)
                            {
                                xmlcartItem.Add(new XElement("ISCHECKOUTOPTION", false));
                                xmlcartItem.Add(new XElement("PRODUCTLINKHREF", productLinkHref));
                            }

                            var matrixDetails = new StringBuilder();
                            var matrixAttributes = AppLogic.GetMatrixItemAttributes(cartItem.ItemCode, Customer.Current.LanguageCode);

                            //Iterate through matrix attributes and append it to the details
                            matrixAttributes.ForEach(item =>
                            {
                                matrixDetails.AppendFormat("&nbsp;&nbsp;{0}:{1}<br />", Security.HtmlEncode(item.AttributeValue), Security.HtmlEncode(item.AttributeValueDescription));
                            });

                            xmlcartItem.Add(new XElement("MatrixDetails", matrixDetails.ToString()));
                            break;

                        #endregion

                        #region "ITEM_TYPE_KIT"
                        case Interprise.Framework.Base.Shared.Const.ITEM_TYPE_KIT:

                            if (showLinkBack && !cartItem.IsCheckoutOption)
                            {
                                xmlcartItem.Add(new XElement("ISCHECKOUTOPTION", false));
                                xmlcartItem.Add(new XElement("PRODUCTLINKHREF", productLinkHref));
                            }

                            var kitItems = new XElement("KIT_ITEMS");
                            string href = InterpriseSuiteEcommerceCommon.InterpriseHelper.MakeItemLink(cartItem.ItemCode) + "?kcid={0}".FormatWith(cartItem.Id.ToString());
                            kitItems.Add(new XElement("KIT_EDIT_HREF", href));
                            kitItems.Add(new XElement("KIT_EDIT_IMAGE_ALT", AppLogic.GetString("mobile.shoppingcart.cs.4", 1, cart.ThisCustomer.LocaleSetting)));

                            bool isCurrencyIncludedForInventorySelling = InterpriseHelper.IsCurrencyIncludedForInventorySelling(cart.ThisCustomer.CurrencyCode);
                            // Special case 2 
                            //  Currency is added in Inventory Selling Currency late
                            //  after the kit has been created, ideally the kit should regenerate kit pricing for this currency
                            //  but for the meantime, we should handle this by looking into the home currency
                            bool currencyIsIncludedInInventorySellingCurrencyButHasNoKitPricingDetailYetForThisItem =
                            InterpriseHelper.CurrencyIsIncludedInInventorySellingCurrencyButHasNoKitPricingDetailYet(cart.ThisCustomer.CurrencyCode, cartItem.ItemCode);

                            // read the records from the EcommerceKitCart table...
                            kitItems.Add(new XElement("KIT_SHOWDETAILSTEXT", AppLogic.GetString("mobile.wishlist.aspx.2", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                            kitItems.Add(new XElement("KIT_HIDEDETAILSTEXT", AppLogic.GetString("mobile.wishlist.aspx.3", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                            var lstKitDetails = AppLogic.GetKitDetail(cartItem.ItemCode,
                                                                      CommonLogic.IIF((isCurrencyIncludedForInventorySelling && !currencyIsIncludedInInventorySellingCurrencyButHasNoKitPricingDetailYetForThisItem), cart.ThisCustomer.CurrencyCode, Currency.GetHomeCurrency()),
                                                                      cart.ThisCustomer.LocaleSetting,
                                                                      cart.ThisCustomer.CustomerCode,
                                                                      cartItem.Id, 
                                                                      cart.ThisCustomer.ContactCode);

                            lstKitDetails.ForEach(item => {
                                kitItems.Add(new XElement("KITITEM", Security.HtmlEncode(string.Format("({0}) {1}", Localization.ParseLocaleDecimal(item.Quantity, cart.ThisCustomer.LocaleSetting).TryParseInt().Value, Security.HtmlEncode(item.Name)))));
                            });

                            xmlcartItem.Add(kitItems);
                            break;
                        #endregion

                        #region "STOCK"
                        default:
                            if (showLinkBack)
                            {
                                if (!cartItem.IsCheckoutOption)
                                {
                                    xmlcartItem.Add(new XElement("ISCHECKOUTOPTION", false));
                                    xmlcartItem.Add(new XElement("PRODUCTLINKHREF", productLinkHref));
                                }
                                else
                                {
                                    //checkout options should only display a popup and not go to a product page
                                    //output.AppendFormat(
                                    //    "<a onclick=\"popuporderoptionwh('Order Option {0}',{1},650,550,'yes');\" href=\"javascript:void(0);\"><b>{0}</b></a><br>",
                                    //    Security.HtmlEncode(cartItem.DisplayName),
                                    //    cartItem.ItemCounter.ToString()
                                    //);
                                }
                            }
                            break;
                        #endregion
                    }

                    #region "Product Picture"

                    if (showPicsInCart)
                    {
                        xmlcartItem.Add(new XElement("SHOWPICSINCART", true));
                        var img = ProductImage.Locate("product", cartItem.ItemCounter, "icon");
                        if (null != img)
                        {
                            string seTitle = "";
                            string seAltText = "";
                            string itemCode = itemCode = InterpriseHelper.GetInventoryItemCode(cartItem.ItemCounter);
                            AppLogic.GetSEImageAttributes(itemCode, "ICON", AppLogic.GetLanguageCode(cart.ThisCustomer.LocaleSetting), ref seTitle, ref seAltText);

                            xmlcartItem.Add(new XElement("PRODUCTIMAGEPATH", img.src));
                            xmlcartItem.Add(new XElement("PRODUCTIMAGETITLE", seTitle));
                            xmlcartItem.Add(new XElement("PRODUCTIMAGEALT", seAltText));
                        }
                    }

                    #endregion

                    #region "Multiple Address"
                    /*************** multiple address **********************/
                    if (cart.HasMultipleShippingAddresses() && !cartItem.IsDownload)
                    {
                        xmlcartItem.Add(new XElement("HAS_MULTIPLE_ADDRESSES", true));
                        xmlcartItem.Add(new XElement("ITEMISDOWNLOAD", false));
                        xmlcartItem.Add(new XElement("SHIP_ITEM_TO_TEXT", AppLogic.GetString("mobile.shoppingcart.cs.24", cart.SkinID, cart.ThisCustomer.LocaleSetting)));

                        xmlcartItem.Add(new XElement("MULTIPLE_SHOWDETAILSTEXT", AppLogic.GetString("mobile.shoppingcart.aspx.50", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                        xmlcartItem.Add(new XElement("MULTIPLE_HIDEDETAILSTEXT", AppLogic.GetString("mobile.shoppingcart.aspx.51", cart.SkinID, cart.ThisCustomer.LocaleSetting)));

                        var adr = new Address();
                        bool includename = true;

                        string shippingName = string.Empty;
                        if (cartItem.m_ShippingAddressID == cart.ThisCustomer.PrimaryShippingAddressID)
                        {
                            adr.LoadByCustomer(cart.ThisCustomer, AddressTypes.Shipping, cartItem.m_ShippingAddressID);
                            shippingName = AppLogic.GetString("account.aspx.10", cart.SkinID, cart.ThisCustomer.LocaleSetting);
                        }
                        else if (cartItem.m_ShippingAddressID == cart.ThisCustomer.PrimaryBillingAddressID)
                        {
                            adr.LoadByCustomer(cart.ThisCustomer, AddressTypes.Billing, cartItem.m_ShippingAddressID);
                            shippingName = AppLogic.GetString("account.aspx.8", cart.SkinID, cart.ThisCustomer.LocaleSetting);
                        }
                        else
                        {
                            adr.LoadByCustomer(cart.ThisCustomer, AddressTypes.Shipping, cartItem.m_ShippingAddressID);
                            shippingName = adr.Name;
                            includename = false;
                        }

                        xmlcartItem.Add(new XElement("SHIP_ITEM_TO_VALUE", shippingName));
                        xmlcartItem.Add(new XElement("SHIP_ITEM_DETAIL", adr.DisplayString(false, false, includename, "<br>")));
                        xmlcartItem.Add(new XElement("SHIPING_METHOD_TEXT", AppLogic.GetString("order.cs.23", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                        xmlcartItem.Add(new XElement("SHIPING_METHOD_VALUE", cartItem.m_ShippingMethod));
                    }

                    #endregion

                    #region "Stock Hints"

                    if (showStockHints)
                    {
                        xmlcartItem.Add(new XElement("SHOWSTOCKHINTS", true));
                        if (showShipDateInCart)
                        {
                            string localizedQty = Localization.ParseLocaleDecimal(cartItem.m_AllocatedQty, cart.ThisCustomer.LocaleSetting);
                            xmlcartItem.Add(new XElement("SHOWSHIPDATEINCART", true));
                            xmlcartItem.Add(new XElement("ALLOCATEDQTY", localizedQty));

                            //with allocation without reservation
                            if (cartItem.m_AllocatedQty > 0)
                            {
                                xmlcartItem.Add(new XElement("SHIPPING_TEXT", AppLogic.GetString("mobile.shoppingcart.cs.2", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                            }

                            var reserveCol = cart.GetReservation(cartItem.ItemCode);
                            if (reserveCol.Count > 0) xmlcartItem.Add(new XElement("SHIPPINGON_TEXT", AppLogic.GetString("mobile.shoppingcart.cs.3", cart.SkinID, cart.ThisCustomer.LocaleSetting)));

                            xmlcartItem.Add(new XElement("RESERVATION_COUNT", reserveCol.Count));
                            var reservationItems = reserveCol
                                    .Select(r => new XElement("RESERVATIONITEM",
                                            new XElement("RESERVE_ITEMCODE", r.ItemCode),
                                            new XElement("RESERVE_SHIPDATE", r.ShipDate.ToShortDateString()),
                                            new XElement("RESERVE_QTY", Localization.ParseLocaleDecimal(r.QtyReserved, cart.ThisCustomer.LocaleSetting))));
                            xmlcartItem.Add(reservationItems);
                        }
                    }

                    #endregion

                    #region "Unit Measure"

                    if (!hideUnitMeasure)
                    {
                        xmlcartItem.Add(new XElement("NOT_HIDE_UNIT_MEASURE", true));
                        var availableUnitMeasures = AppLogic.GetAvailableUnitMesure(cart.ThisCustomer.CustomerCode, cartItem.ItemCode, AppLogic.AppConfigBool("ShowInventoryFromAllWarehouses"), cart.ThisCustomer.IsNotRegistered);

                        if (availableUnitMeasures.Count > 1)
                        {
                            xmlcartItem.Add(new XElement("AVAILABLEUNITMESSURE_GREATER_ONE", true));
                            xmlcartItem.Add(new XElement("MULTIPLE_UNITMEASURECODENAME", "UnitMeasureCode_{0}".FormatWith(cartItem.m_ShoppingCartRecordID)));
                            xmlcartItem.Add(new XElement("MULTIPLE_UNITMEASURECODEID", "UnitMeasureCode_{0}".FormatWith(cartItem.m_ShoppingCartRecordID)));

                            foreach (var unitMeasureValue in availableUnitMeasures)
                            {
                                var unitmeasures = new XElement("UNITMEASSURE_ITEM");
                                xmlcartItem.Add(unitmeasures);
                                bool isCurrentUnitMeasureTheOneSelectedInProductPage = cartItem.UnitMeasureCode.Equals(unitMeasureValue.Key, StringComparison.InvariantCultureIgnoreCase);
                                unitmeasures.Add(new XElement("VALUE", unitMeasureValue.Key.ToHtmlEncode()));
                                unitmeasures.Add(new XElement("TEXT", unitMeasureValue.Value));
                                unitmeasures.Add(new XElement("SELECTED", isCurrentUnitMeasureTheOneSelectedInProductPage));
                            }
                        }
                        else
                        {
                            xmlcartItem.Add(new XElement("AVAILABLEUNITMESSURE_GREATER_ONE", false));
                            xmlcartItem.Add(new XElement("UNITMEASURECODEID", "UnitMeasureCode_{0}".FormatWith(cartItem.m_ShoppingCartRecordID)));
                            xmlcartItem.Add(new XElement("UNITMEASURECODENAME", "UnitMeasureCode_{0}".FormatWith(cartItem.m_ShoppingCartRecordID)));
                            xmlcartItem.Add(new XElement("UNITMEASURECODEVALUE", cartItem.UnitMeasureCode.ToHtmlEncode()));
                            xmlcartItem.Add(new XElement("UNITMEASURECODESPANDISPLAY", availableUnitMeasures[0].Value.ToHtmlEncode()));
                        }
                    }

                    #endregion

                    #region "Input Quantities and Delete"

                    xmlcartItem.Add(new XElement("ISRESTRICTEDQUANTITIES", (cartItem.RestrictedQuantities.Count > 0)));
                    if (cartItem.RestrictedQuantities.Count > 0)
                    {
                        xmlcartItem.Add(new XElement("QUANTITYLISTID", cartItem.m_ShoppingCartRecordID));
                        xmlcartItem.Add(cartItem.RestrictedQuantities
                                    .Select(r => new XElement("RESTRICTEDQUANTITIES",
                                            new XElement("QTY", r),
                                            new XElement("SELECTED", r == cartItem.m_Quantity))));
                    }
                    else
                    {
                        xmlcartItem.Add(new XElement("INPUTQUANTITYID", "Quantity_{0}".FormatWith(cartItem.m_ShoppingCartRecordID)));
                        xmlcartItem.Add(new XElement("INPUTQUANTITYVALUE", Localization.ParseLocaleDecimal(cartItem.m_Quantity, cart.ThisCustomer.LocaleSetting)));
                    }

                    if (AppLogic.AppConfigBool("ShowCartDeleteItemButton"))
                    {
                        xmlcartItem.Add(new XElement("SHOWCARTDELETEITEMBUTTON", true));
                        string deleteCaption = AppLogic.GetString("shoppingcart.cs.31", cart.SkinID, cart.ThisCustomer.LocaleSetting);
                        deleteCaption = string.IsNullOrEmpty(deleteCaption) ? "Delete" : deleteCaption;
                        xmlcartItem.Add(new XElement("DELETECAPTION", deleteCaption));
                    }

                    xmlcartItem.Add(new XElement("MINORDERQUANTITYID", "MinOrderQuantity_{0}".FormatWith(cartItem.m_ShoppingCartRecordID)));
                    xmlcartItem.Add(new XElement("MINORDERQUANTITYNAME", "MinOrderQuantity_{0}".FormatWith(cartItem.m_ShoppingCartRecordID)));
                    xmlcartItem.Add(new XElement("MINORDERQUANTITYVALUE", cartItem.m_MinimumQuantity));

                    #endregion

                    #region "Subtotal"

                    string priceFormatted = InterpriseHelper.FormatCurrencyForCustomer(cartItem.Price, cart.ThisCustomer.CurrencyCode);
                    xmlcartItem.Add(new XElement("PRICEFORMATTED", priceFormatted));

                    string vatDisplayIfIncluded = string.Empty;

                    xmlcartItem.Add(new XElement("VATENABLED", vatenabled.ToStringLower()));
                    if (vatenabled)
                    {
                        if (cart.ThisCustomer.VATSettingReconciled == VatDefaultSetting.Inclusive)
                        {
                            vatDisplayIfIncluded = AppLogic.GetString("showproduct.aspx.38", cart.ThisCustomer.SkinID, cart.ThisCustomer.LocaleSetting);
                            xmlcartItem.Add(new XElement("VAT_TEXT", AppLogic.GetString("showproduct.aspx.41", cart.ThisCustomer.SkinID, cart.ThisCustomer.LocaleSetting)));
                            xmlcartItem.Add(new XElement("TAX_RATE_VALUE", cart.ThisCustomer.FormatBasedOnMyCurrency(cartItem.TaxRate)));
                        }
                        else
                        {
                            vatDisplayIfIncluded = AppLogic.GetString("showproduct.aspx.37", cart.ThisCustomer.SkinID, cart.ThisCustomer.LocaleSetting);
                        }
                        xmlcartItem.Add(new XElement("ITEM_VAT_TEXT", vatDisplayIfIncluded));
                    }

                    #endregion
                }

                string subTotalFormatted = InterpriseHelper.FormatCurrencyForCustomer(cart.GetCartSubTotal(), cart.ThisCustomer.CurrencyCode);
                root.Add(new XElement("SUBTOTAL_TEXT", AppLogic.GetString("shoppingcart.cs.27", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                root.Add(new XElement("SUBTOTAL_VALUE", subTotalFormatted));

                root.Add(new XElement("SHIPPINGCALCULATED_TEXT", AppLogic.GetString("shoppingcart.aspx.10", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                root.Add(new XElement("SHIPPINGCALCULATED_TEXT_2", AppLogic.GetString("shoppingcart.aspx.12", cart.SkinID, cart.ThisCustomer.LocaleSetting)));

                root.Add(new XElement("VATENABLED", vatenabled));
                root.Add(new XElement("TAXCALCULATED_TEXT", AppLogic.GetString("shoppingcart.aspx.11", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                root.Add(new XElement("TAXCALCULATED_TEXT_2", AppLogic.GetString("shoppingcart.aspx.12", cart.SkinID, cart.ThisCustomer.LocaleSetting)));

                string couponCode = string.Empty;
                string couponErrorMessage = string.Empty;
                root.Add(new XElement("HASCOUPON", cart.HasCoupon(ref couponCode)));
                root.Add(new XElement("ISCOUPON_VALID", cart.IsCouponValid(cart.ThisCustomer, couponCode, ref couponErrorMessage)));

                decimal couponDiscount = InterpriseHelper.GetCouponDiscountApplied(cart);
                root.Add(new XElement("COUPON_TEXT", AppLogic.GetString("shoppingcart.cs.38", cart.SkinID, cart.ThisCustomer.LocaleSetting)));
                root.Add(new XElement("COUPON_TEXT2", InterpriseHelper.FormatCurrencyForCustomer(couponDiscount, cart.ThisCustomer.CurrencyCode)));

                string html = new XmlPackage2("page.shoppingcart_items_template.xml.config", root).TransformString();
                output.Append(html);
            }
        }

        #endregion
    }
}
